package com.kedacom.demo.repository;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.kedacom.demo.cache.CacheConstants;
import com.kedacom.demo.cache.annotation.LoadFromCache;
import com.kedacom.demo.cache.annotation.UpdateCollection;
import com.kedacom.demo.cache.annotation.UpdateToCache;
import com.kedacom.demo.domain.User;
import com.kedacom.demo.exception.BusinessException;

/**
 * UserDaoImpl
 * @author luocanfeng
 * @date 2014-7-18
 */
@Repository("userDao")
public class UserDaoImpl extends BaseJdbcDaoSupport implements UserDao {

	static final RowMapper<User> ROW_MAPPER = new RowMapper<User>() {

		@Override
		public User mapRow(ResultSet rs, int rowNum) throws SQLException {
			User user = new User();
			user.setId(rs.getInt("id"));
			user.setUsername(rs.getString("username"));
			user.setPassword(rs.getString("password"));
			user.setName(rs.getString("name"));
			user.setEmail(rs.getString("email"));
			return user;
		}
	};

	private static final String SAVE_SQL = "insert into users(username, password, name, email) values(?, ?, ?, ?)";

	public void save(User user) {
		try {
			Connection connection = super.getConnection();
			PreparedStatement statement = connection.prepareStatement(SAVE_SQL, Statement.RETURN_GENERATED_KEYS);
			statement.setString(1, user.getUsername());
			statement.setString(2, user.getPassword());
			statement.setString(3, user.getName());
			statement.setString(4, user.getEmail());
			statement.execute();
			ResultSet rs = statement.getGeneratedKeys();
			while (rs.next()) {
				user.setId(rs.getInt(1));
			}
			rs.close();
			statement.close();
			logger.debug("saved {}", user);
		} catch (SQLException e) {
			throw new BusinessException("Database exception", e);
		}
	}

	private static final String GET_BY_ID_SQL = "select * from users where id=?";

	@LoadFromCache(prefix = CacheConstants.CACHE_PREFIX_USER_ID2USER, key = "${id}")
	public User get(Integer id) {
		User user = super.queryUniqueEntity(GET_BY_ID_SQL, ROW_MAPPER, id);
		logger.debug("get {} from database", user);
		return user;
	}

	private static final String GET_ID_BY_EMAIL_SQL = "select id from users where email=?";

	@LoadFromCache(prefix = CacheConstants.CACHE_PREFIX_USER_EMAIL2ID, key = "${email}")
	public Integer getIdByEmail(String email) {
		return super.queryUniqueEntity(GET_ID_BY_EMAIL_SQL, INTEGER_ROW_MAPPER, email);
	}

	private static final String UPDATE_SQL = "update users set username=?, password=?, name=?, email=? where id=?";

	@UpdateCollection({
			@UpdateToCache(prefix = CacheConstants.CACHE_PREFIX_USER_ID2USER, key = "${user.id}"),
			@UpdateToCache(prefix = CacheConstants.CACHE_PREFIX_USER_EMAIL2ID, key = "${user.email}")
	})
	public void update(User user) {
		super.getJdbcTemplate().update(UPDATE_SQL, user.getUsername(), user.getPassword(), user.getName(),
				user.getEmail());
		logger.debug("updated {}", user);
	}

	private static final String LIST_ALL_SQL = "select * from users";

	// 这里有另外一个做法，就是获取所有用户的ID，然后从缓存遍历
	public List<User> listAll() {
		return super.getJdbcTemplate().query(LIST_ALL_SQL, ROW_MAPPER);
	}

}
